package com.atguigu.dga.assess.assessor.security;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.dga.assess.assessor.AssessorTemplate;
import com.atguigu.dga.assess.bean.AssessParam;
import com.atguigu.dga.assess.bean.GovernanceAssessDetail;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Smexy on 2023/11/2

 检查该表最高权限的目录或者文件，如果超过文件超过{file_permission}或者目录超过{dir_permission}则给0分 其余给10分
 */
@Component("PERMISSION_CHECK")
public class CheckFilePermission extends AssessorTemplate
{
    @Autowired
    private ApplicationContext context;
    @Override
    protected void assess(AssessParam param, GovernanceAssessDetail detail) throws Exception {
        //取参数
        Integer file_permission = getIntegerValueFromConfig(param, "file_permission");
        Integer dir_permission = getIntegerValueFromConfig(param, "dir_permission");
        //取表目录
        String tableFsPath = param.getMetaInfo().getTableFsPath();
        //准备客户端
        FileSystem hdfs = context.getBean(FileSystem.class);
        //准备一个结果
        List<JSONObject> result = new ArrayList<>();
        //遍历表目录，找到超出权限的文件
        FileStatus[] fileStatuses = hdfs.listStatus(new Path(tableFsPath));
        //遍历表的子目录
        comparePermission(hdfs,fileStatuses,file_permission,dir_permission,result);
        //检测当前表目录是否也超过权限
        FileStatus fileStatus = hdfs.getFileStatus(new Path(tableFsPath));
        int tablePathPermission = getPermission(fileStatus);

        hdfs.close();
        if (tablePathPermission > dir_permission){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("目录名",tableFsPath);
            jsonObject.put("权限",tablePathPermission);
            jsonObject.put("规定的权限",dir_permission);
            result.add(jsonObject);
        }
        //收集了一些结果
        if (result.isEmpty()){
            return ;
        }

        assessScore(BigDecimal.ZERO,"表目录权限异常", JSON.toJSONString(result),detail,false,null);

    }

    //只比较表中的其他子目录的权限
    private void comparePermission(FileSystem hdfs, FileStatus[] fileStatuses, Integer file_permission, Integer dir_permission, List<JSONObject> result) throws IOException {

        for (FileStatus fileStatus : fileStatuses) {
            //获取到当前这个目录的权限
            int permission = getPermission(fileStatus);
            if (fileStatus.isFile() ){
                if (permission > file_permission){
                    //记录问题
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("文件名",fileStatus.getPath().toString());
                    jsonObject.put("权限",permission);
                    jsonObject.put("规定的权限",file_permission);
                    result.add(jsonObject);
                }

            }else {
                //是目录
                if (permission > dir_permission){
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("目录名",fileStatus.getPath().toString());
                    jsonObject.put("权限",permission);
                    jsonObject.put("规定的权限",dir_permission);
                    result.add(jsonObject);
                }
                FileStatus[] subFileStatus = hdfs.listStatus(fileStatus.getPath());
                //递归判断
                comparePermission(hdfs,subFileStatus,file_permission,dir_permission,result);
            }
        }


    }


    private int getPermission(FileStatus fileStatus) throws IOException {

        FsPermission permission = fileStatus.getPermission();
        //把字符串的权限转换为 数值
        /*  user group  other
            rwx  r-x     r-x
            111  101     101
            7    5       5
            有权限，记为1，没有(-)，记为0
         */
       return permission.getUserAction().ordinal()*100
           + permission.getGroupAction().ordinal()*10
           + permission.getOtherAction().ordinal();
    }
}
